package com.orientation.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.orientation.commom.exception.CustomException;
import com.orientation.entity.Bed;
import com.orientation.entity.Building;
import com.orientation.entity.Room;
import com.orientation.mapper.BuildingMapper;
import com.orientation.mapper.RoomMapper;
import com.orientation.service.BedService;
import com.orientation.service.BuildingService;
import com.orientation.service.RoomService;
import com.orientation.utils.PageUtils;
import com.orientation.vo.BuildingRoomVo;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.text.CollationKey;
import java.text.Collator;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 报到 服务实现类
 * </p>
 *
 * @author xuandian
 * @since 2022-3-9
 */
@Service
public class BuildingServiceImpl extends ServiceImpl<BuildingMapper, Building> implements BuildingService {
    @Resource
    private BuildingMapper buildingMapper;
    @Resource
    private BuildingService buildingService;
    @Resource
    private RoomMapper roomMapper;
    @Resource
    private RoomService rosService;
    @Resource
    private BedService bedService;


    public BuildingServiceImpl() {

    }

    @Override
    public void insertBuild(Building building) {
        if (building != null && StringUtils.hasLength(building.getName()) && StringUtils.hasLength(building.getFloor())) {
//获取楼层类型
            Building building1 = buildingMapper.selectOne(new LambdaQueryWrapper<Building>().eq(Building::getName, building.getName()).last("limit 1"));
            Building oneBuilding = buildingMapper.selectOne(new LambdaQueryWrapper<Building>().eq(Building::getName, building.getName()).eq(Building::getFloor, building.getFloor()));
            if (oneBuilding != null) {
                throw new CustomException("18", "此公寓已经存在，请不要重复添加");
            }
            if (!StringUtils.hasLength(building.getRegion())) {
                throw new CustomException("18", "请填写所属校区");
            }
            if (!StringUtils.hasLength(building.getType())) {
                throw new CustomException("18", "请填写男生公寓还是女生公寓");
            }
            if (StringUtils.hasLength(building.getType()) && building.getType().length() != 4) {
                throw new CustomException("18", "公寓长度填写错误");
            }
            if (StringUtils.hasLength(building.getType()) && building1 != null && !building.getType().equals(building1.getType())) {
                throw new CustomException("18", "公寓类型不能无法修改");
            }
            if (!StringUtils.hasLength(building.getFloor())) {
                throw new CustomException("18", "请填写楼层数");
            }
            if (building1 != null) {
                building.setType(building1.getType());
            }
            save(building);
        } else {
            throw new CustomException("18", "请填写必要信息");
        }
    }

    @Override
    public void updateBuilding(Building building) {
        if (building != null && building.getName() != null) {
            Building oneBuilding = buildingMapper.selectOne(new LambdaQueryWrapper<Building>().eq(Building::getName, building.getName()));
            if (oneBuilding != null) {
                throw new CustomException(" 18", "此公寓已经存在，请不要重复添加");
            }
        }
        updateById(building);
    }

    @Override
    public IPage<Building> getBuilding(Integer pageNum, Integer pageSize, String region, String name, String type) {
        List<Building> buildingList = buildingList(region, name, type);
        return PageUtils.getPage(buildingList, pageNum, pageSize);
    }

    @Override
    public Page<BuildingRoomVo> queryBuildingVo(Integer pageNum, Integer pageSize, String region, String name, String type) {
        List<BuildingRoomVo> buildingRoomVos = new ArrayList<BuildingRoomVo>();
        List<Building> buildingList = buildingList(region, name, type);
//
        if (!CollectionUtils.isEmpty(buildingList)) {
            Map<String, List<Building>> listMap = buildingList.stream().collect(Collectors.groupingBy(Building::getName));
            List<BuildingRoomVo> finalBuildingRoomVos = buildingRoomVos;
            listMap.forEach((buildingName, value) -> {
                BuildingRoomVo buildingRoomVo = new BuildingRoomVo();
                buildingRoomVo.setName(buildingName);
                buildingRoomVo.setType(value.get(0).getType());
                buildingRoomVo.setFloorNum(value.size());
                buildingRoomVo.setRegion(value.get(0).getRegion());
                List<Building> buildings = new ArrayList<>();
                buildingRoomVo.setBuildingList(value);
                for (Building buildin : value) {
                    List<Room> roomList = roomMapper.selectList(new LambdaQueryWrapper<Room>().eq(Room::getBuildingId, buildin.getSid()).eq(Room::getFloor, buildin.getFloor()));
                    buildin.setRoomList(roomList);
                    buildings.add(buildin);
                }
                buildingRoomVo.setBuildingList(buildings);
                finalBuildingRoomVos.add(buildingRoomVo);
            });
            buildingRoomVos = finalBuildingRoomVos.stream().sorted(Comparator.comparing(BuildingRoomVo::getName)).collect(Collectors.toList());
        }
        return PageUtils.getPage(buildingRoomVos, pageNum, pageSize);

    }

    @Override
    public BuildingRoomVo createBuildingRoom(String region, String name, String type) {
        LambdaQueryWrapper<Building> query = new LambdaQueryWrapper<>();
        if (StringUtils.hasLength(region)) {
            query.like(Building::getRegion, region);
        }
        if (!StringUtils.hasLength(name)) {
            throw new CustomException("18", "请选择公寓名");
        }
        if (StringUtils.hasLength(name)) {
            query.like(Building::getName, name);
        }
        if (StringUtils.hasLength(type)) {
            query.like(Building::getType, type);
        }
        List<Building> buildings = buildingMapper.selectList(query);
        BuildingRoomVo buildingRoomVo = new BuildingRoomVo();
        //排序
        buildingRoomVo.setBuildingList(comparatorChina(buildings));

        List<String> floorsSid = buildings.stream().map(Building::getSid).distinct().collect(Collectors.toList());
        Map<String, List<Building>> listMap = buildings.stream().collect(Collectors.groupingBy(Building::getName));
        List<BuildingRoomVo> finalBuildingRoomVos = new ArrayList<>();
        listMap.forEach((buildingName, value) -> {
            buildingRoomVo.setName(buildingName);
            buildingRoomVo.setType(value.get(0).getType());
            buildingRoomVo.setFloorNum(value.size());
            buildingRoomVo.setBuildingList(value);
            buildingRoomVo.setRegion(value.get(0).getRegion());
            for (Building buildin : value) {
                List<Room> roomList = roomMapper.selectList(new LambdaQueryWrapper<Room>().eq(Room::getBuildingId, buildin.getSid()).eq(Room::getFloor, buildin.getFloor()));
                buildin.setRoomList(comparatorForChina(roomList));
            }
        });
        List<Room> rooms = rosService.list(Wrappers.<Room>lambdaQuery().in(!CollectionUtils.isEmpty(floorsSid), Room::getBuildingId, floorsSid));
        Building newBuilding = new Building();
        newBuilding.setRoomList(rooms);
        return buildingRoomVo;
    }

    @Override
    public List<Building> getAll() {
        List<Building> buildings = buildingService.list();
        List<Building> distinct = buildings.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Building::getName).thenComparing(Building::getFloor))), ArrayList::new));
        comparatorChina(distinct);
        return distinct;
    }

    @Override
    public List<Building> queryBuildingType(String type) {
        List<Building> buildingList = new ArrayList<>();
        List<Bed> beds = bedService.list(Wrappers.<Bed>lambdaQuery().isNull(Bed::getStudentId));
        if (!CollectionUtils.isEmpty(beds)) {
            List<String> roomIds = beds.stream().map(Bed::getRoomId).distinct().collect(Collectors.toList());
            List<Room> roomList = rosService.list(Wrappers.<Room>lambdaQuery().in(!CollectionUtils.isEmpty(roomIds), Room::getSid, roomIds));
            List<String> buildingIds = roomList.stream().map(Room::getBuildingId).distinct().collect(Collectors.toList());
            List<Building> buildings = this.list(Wrappers.<Building>lambdaQuery().in(Building::getSid, buildingIds));
            List<Building> collect = buildings.stream().filter((Building b) -> type.equals(b.getType())).collect(Collectors.toList());
            buildingList = collect.stream().filter((Building b) -> b.getRoom() != null && b.getRoom() > 0).collect(Collectors.toList());
        }
        return buildingList;
    }

    @Override
    public List<String> queryAreaList(String type) {
        List<Building> buildings = queryBuildingType(type);
        // List<Building> list = buildings.stream().sorted(Comparator.comparing(Building::getName).thenComparing(Building::getFloor)).collect(Collectors.toList());
        List<String> distinctList = buildings.stream().map(Building::getName).collect(Collectors.toList());
        //中文首字母排序
        Collections.sort(distinctList, new Comparator<String>() {
            Collator collator = Collator.getInstance(Locale.CHINA);

            @Override
            public int compare(String o1, String o2) {
                CollationKey key1 = collator.getCollationKey(o1);
                CollationKey key2 = collator.getCollationKey(o2);
                return key1.compareTo(key2);
            }
        });
        return distinctList;
    }

    private List<Building> buildingList(String region, String name, String type) {
        LambdaQueryWrapper<Building> query = new LambdaQueryWrapper<>();
        if (StringUtils.hasLength(region)) {
            query.like(Building::getRegion, region);
        }
        if (StringUtils.hasLength(name)) {
            query.like(Building::getName, name);
        }
        if (StringUtils.hasLength(type)) {
            query.like(Building::getType, type);
        }
        List<Building> buildingList = buildingMapper.selectList(query).stream().sorted(Comparator.comparing(Building::getRegion)).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(buildingList)) {
            throw new CustomException("18", "当前暂无数据");
        }
        return buildingList;
    }

    /**
     * 按中文首字母排序
     *
     * @param result
     * @return result
     */
    private List<Room> comparatorForChina(List<Room> result) {
        Comparator comparator = Collator.getInstance(Locale.CHINA);
        Collections.sort(result, (o1, o2) -> comparator.compare(o1.getName(), o2.getName()));
        return result;
    }

    /**
     * 按中文首字母排序
     *
     * @param result
     * @return result
     */
    private List<Building> comparatorChina(List<Building> result) {
        Comparator comparator = Collator.getInstance(Locale.CHINA);
        Collections.sort(result, (o1, o2) -> comparator.compare(o1.getFloor(), o2.getFloor()));
        return result;
    }


}
